package grammar.parser;

import error.processing.MyErrorProcessing;
import exp.parser.ConstExp;
import semantic.parser.SymbolTableElement;
import word.parser.WordElement;

import java.util.ArrayList;
import java.util.List;

public class ConstDecl extends Decl {
    private final List<Integer> value;

    public ConstDecl(String ident, int dimension, List<Integer> lenOfDimension, List<Integer> value) {
        super(true, ident, dimension, lenOfDimension);
        this.value = value;
    }

    public static List<ConstDecl> buildConstDecl() {
        assert getAnalyzingWord().getType() == WordElement.WordType.CONSTTK;
        analyzeNextWord();
        assert getAnalyzingWord().getType() == WordElement.WordType.INTTK;
        analyzeNextWord();
        List<ConstDecl> ans;
        ans = buildConstDef();
        return ans;
    }

    public static List<ConstDecl> buildConstDef() {
        List<ConstDecl> constDecls = new ArrayList<>();
        do {
            assert getAnalyzingWord().getType() == WordElement.WordType.IDENFR;
            int identPosition = getNowPosition();
            String ident = getAnalyzingWord().getWord();
            int dimension = 0;
            ArrayList<Integer> lenOfDimension = new ArrayList<>();
            analyzeNextWord();
            while (getAnalyzingWord().getType() == WordElement.WordType.LBRACK) {
                dimension++;
                analyzeNextWord();
                lenOfDimension.add(ConstExp.buildAndCompute().getValue());
                if (getAnalyzingWord().getType() != WordElement.WordType.RBRACK) {
                    MyErrorProcessing.buildErrorProcessing(MyErrorProcessing.ErrorType.k,
                            getAnalyzingWord(-1));
                } else {
                    analyzeNextWord();
                }
            }
            assert getAnalyzingWord().getType() == WordElement.WordType.ASSIGN;
            analyzeNextWord();
            List<Integer> initVal = new ArrayList<>();
            constInitVal(initVal);
            //符号表
            getSemanticParser().declVariable(getWord(identPosition),
                    SymbolTableElement.SymbolType.CONST_INT, getScope(),
                    dimension, lenOfDimension, initVal, new ArrayList<>());
            constDecls.add(new ConstDecl(ident, dimension, lenOfDimension, initVal));
            if (getAnalyzingWord().getType() == WordElement.WordType.COMMA) {
                analyzeNextWord();
            } else if (getAnalyzingWord().getType() == WordElement.WordType.SEMICN) {
                analyzeNextWord();
                break;
            } else {
                MyErrorProcessing.buildErrorProcessing(MyErrorProcessing.ErrorType.i, getAnalyzingWord(-1));
                break;
            }
        } while (true);
        return constDecls;
    }

    public static void constInitVal(List<Integer> cup) {
        if (getAnalyzingWord().getType() == WordElement.WordType.LBRACE) {
            analyzeNextWord();
            if (getAnalyzingWord().getType() != WordElement.WordType.RBRACE) {
                constInitVal(cup);
                while (getAnalyzingWord().getType() == WordElement.WordType.COMMA) {
                    analyzeNextWord();
                    constInitVal(cup);
                }
            }
            assert getAnalyzingWord().getType() == WordElement.WordType.RBRACE;
            analyzeNextWord();
        } else {
            cup.add(ConstExp.buildAndCompute().getValue());
        }
    }

    public List<Integer> getValue() {
        return value;
    }

    @Override
    public void execute() {
        getSemanticParser().declVariable(getIdent(),
                SymbolTableElement.SymbolType.CONST_INT, getScope(),
                getDimension(), getLenOfDimension(), value);
    }
}
